<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>01-ES6 常用新语法</title>
</head>

<body>
    <script>

        /*
            简单的语法
            ● const 与 let
                const和let的区别
                    相同点
                        1、都会产生一个块级作用域
                        2、都没有变量提升
                            会产生一个暂时性死区，暂时性死区里的变量，禁止在初始化之前访问
                        3、不允许重复声明变量
                        4、都不会作用在window上(用var声明的变量，会作用在window上)

                    不同点
                        1、const声明的时候必须赋初始值，let不用
                        2、const定义的是常量，值不能修改，let定义的是变量，值可以修改
            ● 解构赋值
            ● 形参默认值
            ● 扩展运算符: ...
            ● 模板字符串
                 `${}`
            ● 对象的属性与方法简写
            ● 模块化语法
            ● ...
            2. 比较复杂的语法
            ● 箭头函数（引申总结 this 指向）
                箭头函数特点：
                    1、没有自己的this，使用的外侧作用域下的this
                    2、没有显示原型prototype属性,不用使用new的方式创建实例化对象
                    3、不能使用call/apply/bind强行改变this指向
                        Vue中声明周期钩子能不能写成箭头函数?
                    4、没有arguments伪数组
            ● class 与 extend（引申原型和继承）
            ● promise / generator / async & await（引申 js 事件循环机制）
                generator 迭代器
                    使用for of 循环的值，必须要有迭代器对象
            ● Proxy（引申 vue2 和 vue3 响应式原理）
            ● Map / Set / WeakMap / WeakSet (引申 vue3 响应式原理)
                Map 类似于对象      特点：1、key可以是任意数据类型  2、有序
                WeakMap 类似于对象   特点：1、key可以只能是引用类型数据  2、有序  3、key的外部链接断开后，值自动被回收
                Set 类似于数组      特点：1、值是唯一的
                WeakSet 类似于数组  特点：1、值是唯一的   2、值只能是引用数据类型数据   3、值的外部地址链接断开后，值自动被回收
        */
        // if (true) {
        //     console.log(a)
        //     const a = 10;
        // }
        // const a = 10;
        // const a = 10
        // const aaa = 10;
        // console.log(window)
        // let a = 10;
        // a = 20;
        // console.log(a)
        // const obj = {
        //     name: 'tom'
        // }
        // obj = '小花'
        // console.log(obj)

        // var arr = [1, 2, 3, 4];
        // let [a, b, c, d] = arr
        // console.log(a)
        // const obj = {
        //     name: 'tom'
        // }
        // // let { name } = obj

        // let obj2 = {
        //     ...obj
        // }

        // let obj = {
        //     fn: function () { },
        //     fn2() { }
        // }
        // function fn() { }
        // var fn = () => {
        //     console.log(this)
        // }
        // fn.call({})
        // console.log(fn.prototype)
        // function fn() {
        //     console.log(arguments)
        // }
        // var fn = (...reset) => {
        //     console.log(reset)
        // }
        // fn(1, 2, 3)


        // 构造函数继承
        // function Person(name, age) {
        // this.name = name;
        // this.age = age
        // }
        // Person.prototype.say = function () {
        //     console.log('我是好人')
        // }

        // function Student(name, age, price) {
        //     // 1、继承的第一步
        //     Person.call(this, name, age)
        // // this.name = name;
        // // this.age = age
        // this.price = price
        // }

        // // 构造函数继承第二步，该变原型对象的指向
        // Student.prototype = new Person()
        // Student.prototype.study = function () {
        //     console.log('好好学习')
        // }
        // // 构造函数继承第三部=步，该变construcort的指向
        // Student.prototype.constructor = Student
        // let s = new Student('小明', 20, 100000)
        // console.log(s.constructor)
        // // s.study()
        // s.say()

        // class Person {
        //     constructor(name, age) {
        //         this.name = name;
        //         this.age = age
        //     }
        //     // 使用这种形式创建的方法，最终添加到了原型对象上
        //     say() {
        //         console.log('我是好人')
        //     }
        //     // 使用这种形式创建的方法，最终添加到了实例对象上
        //     // say2 = () => { }
        // }

        // class Student extends Person {
        //     constructor(name, age, price) {
        //         // 想当于是构造函数继承里的：Person.call(this, name, age)
        //         super(name, age)
        //         // this.name = name;
        //         // this.age = age
        //         this.price = price
        //     }
        //     study() {
        //         console.log('好好学习')
        //     }
        // }
        // let s = new Student('小强', 18, 2000000)
        // console.log(s)
        // s.say()

        // function* fn() {
        //     yield 1
        //     yield 2
        //     yield 3
        // }
        // let f = fn()
        // console.log(f.next().value)
        // console.log(f.next().value)
        // console.log(f.next().value)
        // console.log(f.next().value) 
        // let arr = [1, 2, 3]
        // console.log(arr)
        // let obj = {
        //     name: 'tom',
        //     age: 20
        // }
        // for (a of obj) {
        //     console.log(a)
        // }
        // let obj = {
        //     bbb: '123',
        //     [{}]: '3333'
        // }

        // obj.aaa = '456'
        // console.log(obj)
        // let m = new Map()
        // m.set({}, '1111')
        // m.set('bbb', '2222')
        // console.log(m)
        // key的外部链接断开后，值自动被回收(被垃圾回收机制进行回收释放)
        // let wm = new WeakMap()
        // let obj = {}
        // wm.set(obj, 123)
        // obj = null
        // console.log(wm)

        // let arr = [1, 2, 3, 3, 2, 4]
        // let s = new Set(arr)
        // console.log(Array.from(s))
        // s.add(1)
        // s.add(2)
        // s.add(1)
        // s.add(3)
        // console.log(s)

        let ws = new WeakSet()
        let obj = {}

        ws.add(obj)
        ws.add({})
        obj = null
        console.log(ws)
    </script>
</body>

</html>